import { ShapeFlags } from "../shared/shapeFlags";
import { vnode, componentInstance, rawSlots, rawSlot_res, slots, vnodeChildren } from "./index.d";

/**初始化slots，把插槽从vnode转为vnode数组
 * @param instance 组件实例
 * @param children 该实例的children
 */
export function initSlots(instance: componentInstance, children: vnodeChildren | undefined) {
  const { vnode } = instance;
  if ((vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) && children) {//如果孩子是slot类型，才干这事  （且 children 不是undefined）
    normalizeObjectSlots(children as rawSlots, instance.slots) //这里是处理slot的函数，children不可能是string
  }
}

/**遍历原插槽rawSlots（即children），处理单个插槽，转为 ()=>vnode[]，放到 slots 中*/
const normalizeObjectSlots = (rawSlots: rawSlots | undefined, slots: slots) => {
  if (!rawSlots) return
  for (const key in rawSlots) {
    const value = rawSlots[key];
    if (typeof value === "function") {
      // 把这个函数给到slots 对象上存起来,后续在 renderSlot函数 中调用
      // TODO 这里没有对 value 做 normalize，默认 slots 返回的就是一个 vnode 对象 
      //在这里， value原本是一个函数，执行之后才能调用 normalizeSlotValue 函数来进行转换。然后我最终有需要一个函数，所以变成一个箭头函数的样子，等到执行这个箭头函数，才会执行 normalizeSlotValue
      slots[key] = (props) => normalizeSlotValue(value(props))
    }
  }
};

/**判断这个单个插槽是不是数组，不是的话就转为数组 */
const normalizeSlotValue = (value: rawSlot_res): vnode[] => {
  return Array.isArray(value) ? value : [value];// 把 function 返回的值从 vnode | vnode[] 转换成 vnode[] ，这样 slot 就可以支持多个元素了
};

